package services

import (
	"encoding/base64"
	"go.uber.org/zap"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"k8soperation/global"
	"k8soperation/internal/app/models"
	"k8soperation/internal/app/requests"
	"k8soperation/internal/errorcode"
	"os"
	"strings"
)

func (s *Services) K8sClusterCreate(param *requests.K8sClusterCreateRequest) error {
	return s.dao.K8sClusterCreate(param.ClusterName, param.ClusterVersion, param.KubeConfig)
}

func (s *Services) K8sClusterUpdate(param *requests.K8sClusterUpdateRequest) error {
	return s.dao.K8sClusterUpdate(param.ID, param.ClusterName, param.ClusterVersion, param.KubeConfig, param.Status)
}

func (s *Services) K8sClusterDelete(param *requests.K8sClusterDeleteRequest) error {
	return s.dao.K8sClusterDelete(param.ID)
}

func (s *Services) K8sClusterList(param *requests.K8sClusterListRequest) ([]*models.K8sCluster, error) {
	return s.dao.K8sClusterList(param.ClusterName, param.Page, param.Limit)
}

// 初始化K8s集群
// 需要的 import：
// import (
//     "encoding/base64"
//     "os"
//     "strings"
//     "go.uber.org/zap"
//     "k8s.io/client-go/kubernetes"
//     "k8s.io/client-go/rest"
//     "k8s.io/client-go/tools/clientcmd"
// )

func (s *Services) K8sClusterInit(param *requests.K8sClusterInitRequest) (*kubernetes.Clientset, error) {
	// 0) 基本入参日志
	global.Logger.Info("K8sClusterInit begin",
		zap.Uint32("cluster_id", param.ID),
	)

	// 1) 数据库取 kubeconfig
	kc, err := s.dao.K8sClusterGetByID(param.ID)
	if err != nil {
		global.Logger.Warn("get cluster by id failed, fallback to global/incluster",
			zap.Uint32("cluster_id", param.ID),
			zap.Error(err),
		)
	} else {
		raw := strings.TrimSpace(kc.KubeConfig)
		if raw != "" {
			// 尝试 base64 解码；失败则当作原始 YAML
			var data []byte
			if decoded, decErr := base64.StdEncoding.DecodeString(raw); decErr == nil {
				data = decoded
				global.Logger.Info("kubeconfig detected as base64",
					zap.Uint32("cluster_id", param.ID),
				)
			} else {
				data = []byte(raw)
				global.Logger.Info("kubeconfig treated as plain YAML",
					zap.Uint32("cluster_id", param.ID),
					zap.String("decode_err_hint", decErr.Error()),
				)
			}

			if cfg, cfgErr := clientcmd.RESTConfigFromKubeConfig(data); cfgErr == nil {
				if cs, csErr := kubernetes.NewForConfig(cfg); csErr == nil {
					global.Logger.Info("init k8s client from DB kubeconfig success",
						zap.Uint32("cluster_id", param.ID),
					)
					return cs, nil
				} else {
					global.Logger.Error("create clientset from DB kubeconfig failed",
						zap.Uint32("cluster_id", param.ID),
						zap.Error(csErr),
					)
					return nil, csErr
				}
			} else {
				global.Logger.Error("parse DB kubeconfig failed",
					zap.Uint32("cluster_id", param.ID),
					zap.Error(cfgErr),
				)
				return nil, cfgErr
			}
		} else {
			global.Logger.Warn("empty kubeconfig in DB",
				zap.Uint32("cluster_id", param.ID),
			)
		}
	}

	// 2) 兜底：全局 kubeconfig 路径
	globalPath := strings.TrimSpace(global.AppSetting.GlobalKubeConfigPath)
	if globalPath != "" {
		if statErr := func() error {
			if _, e := os.Stat(globalPath); e != nil {
				return e
			}
			return nil
		}(); statErr == nil {
			if cfg, cfgErr := clientcmd.BuildConfigFromFlags("", globalPath); cfgErr == nil {
				if cs, csErr := kubernetes.NewForConfig(cfg); csErr == nil {
					global.Logger.Info("init k8s client from global kubeconfig success",
						zap.String("global_path", globalPath),
					)
					return cs, nil
				} else {
					global.Logger.Error("create clientset from global kubeconfig failed",
						zap.String("global_path", globalPath),
						zap.Error(csErr),
					)
					return nil, csErr
				}
			} else {
				global.Logger.Error("parse global kubeconfig failed",
					zap.String("global_path", globalPath),
					zap.Error(cfgErr),
				)
				return nil, cfgErr
			}
		} else {
			global.Logger.Warn("global kubeconfig path not found",
				zap.String("global_path", globalPath),
				zap.Error(statErr),
			)
		}
	} else {
		global.Logger.Warn("global kubeconfig path is empty in config")
	}

	// 3) 兜底：InCluster（如果你的服务跑在 K8s 集群里）
	if icCfg, icErr := rest.InClusterConfig(); icErr == nil {
		if cs, csErr := kubernetes.NewForConfig(icCfg); csErr == nil {
			global.Logger.Info("init k8s client from in-cluster config success")
			return cs, nil
		} else {
			global.Logger.Error("create clientset from in-cluster config failed",
				zap.Error(csErr),
			)
			return nil, csErr
		}
	} else {
		global.Logger.Warn("in-cluster config not available",
			zap.Error(icErr),
		)
	}

	// 4) 全部失败
	global.Logger.Error("K8sClusterInit failed: no valid kubeconfig source",
		zap.Uint32("cluster_id", param.ID),
		zap.String("global_path", globalPath),
	)
	return nil, errorcode.ErrorClusterInitFailed
}
